<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>OpenMesh: Storing custom properties</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
  $(document).ready(initResizable);
</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="logo_align.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="rwth_vci_rgb.jpg"/></td>
  <td id="projectalign" style="padding-left: 0.5em;">
   <div id="projectname">OpenMesh
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('a04346.html','');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">Storing custom properties </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>The OpenMesh' proprietary OM format allows to store and restore custom properties along with the standard properties.</p>
<p>For it we have to use named custom properties like the following one</p>
 <div class="fragment"><div class="line">  <a class="code" href="a02553.html">OpenMesh::VPropHandleT&lt;float&gt;</a>       vprop_float;</div><div class="line">  mesh.add_property(vprop_float,  <span class="stringliteral">&quot;vprop_float&quot;</span>);</div></div><!-- fragment --></p>
<p>Here we registered a float property for the vertices at the mesh with name "vprop_float". The name of a property, that we want to make persistent, must follow a few rules</p>
<ol type="1">
<li>max. 256 characters long</li>
<li>The prefixes <code>"v:"</code>, <code>"h:"</code>, <code>"e:"</code>, <code>"f:"</code> and <code>"m:"</code> are reserved.</li>
</ol>
<p>If we stick to this rules we are fine. Furthermore we have to consider, that the names are handled case-sensitive.</p>
<p>To actually make a custom property persistent we have to set the persistent flag in the property with</p>
<p><div class="fragment"><div class="line">  mesh.property(vprop_float).set_persistent(<span class="keyword">true</span>);</div></div><!-- fragment --></p>
<p>Now we can use <code>IO::mesh_write()</code> to write the mesh to a file on disk. The custom properties are added after the standard properties in the file, with the name and it's binary size. These two pieces of information are evaluated when reading the file again. To successfully restore the custom properties, the mesh must have registered named properties with equal names (case-sensitive compare). Additionally, when reading the data, the number of bytes read for a property must match the provided number in the file. If the OM reader did not find a suitable named property, it will simply skip it. If the number of bytes do not match, the complete restore will be terminated and <code>IO::read_mesh()</code> will return <code>false</code>. And if the data cannot be restored, because the appropriate restore method is not available the exception std::logic_error() will be thrown.</p>
<p>Since we now know the behaviour, we need to know what kind of data can we store? Without any further effort, simply using named properties and setting the persistent flag, we can store following types</p>
<ul>
<li>bool, stored as a bitset</li>
<li>all other fundamental types except long double, (unsigned) long and size_t</li>
<li>std::string, each up to 65536 characters long</li>
<li>OpenMesh::Vec[1,2,3,4,6][c,uc,s,us,i,ui,f,d]</li>
</ul>
<p>For further reading we call these types basic types. Apparently we cannot store non-basic types, which are</p>
<ul>
<li>pointers</li>
<li>structs/classes</li>
<li>even more complex data structures, like container of containers.</li>
</ul>
<p>However there is a way to store custom types ( else we could not store std::string). Let's start with an more simple custom data. For instance we have a struct <code><a class="el" href="a03429.html">MyData</a></code> like this</p>
 <div class="fragment"><div class="line"><span class="keyword">struct </span><a class="code" href="a03429.html">MyData</a></div><div class="line">{</div><div class="line">  <span class="keywordtype">int</span>             ival;</div><div class="line">  <span class="keywordtype">double</span>          dval;</div><div class="line">  <span class="keywordtype">bool</span>            bval;</div><div class="line">  <a class="code" href="a02005.html">OpenMesh::Vec4f</a> vec4fval;</div><div class="line">};</div></div><!-- fragment --></p>
<p>Here we keep an int, bool, double value and a vector of 4 floats, which are all basic types. Then we need to specialize the template struct OpenMesh::IO::binary&lt;&gt; within the namespace <code><a class="el" href="a01236.html" title="This namespace contains functions for reading and writing polygonal meshes and a list of supported fi...">OpenMesh::IO</a></code> </p>
<p><div class="fragment"><div class="line">    <span class="keyword">template</span> &lt;&gt; <span class="keyword">struct </span>binary&lt;<a class="code" href="a03429.html">MyData</a>&gt;</div></div><!-- fragment --></p>
<p>Remember not to use long double, (unsigned) long and size_t as basic types because of inconsistencies between 32/64bit architectures.</p>
<p>Herein we have to implement the following set of static member variables and functions:</p>
<p><div class="fragment"><div class="line">      <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">bool</span> <a class="code" href="a01236.html#afadc77f8b3e81138828deba328e65421">is_streamable</a> = <span class="keyword">true</span>;</div><div class="line">      <span class="keyword">static</span> <span class="keywordtype">size_t</span> <a class="code" href="a01236.html#a787a7735700a12801c8a505f2c605681">size_of</a>(<span class="keywordtype">void</span>) </div><div class="line">      <span class="keyword">static</span> <span class="keywordtype">size_t</span> <a class="code" href="a01236.html#a787a7735700a12801c8a505f2c605681">size_of</a>(<span class="keyword">const</span> value_type&amp;) </div><div class="line">      <span class="keyword">static</span> <span class="keywordtype">size_t</span> store(std::ostream&amp; _os, <span class="keyword">const</span> value_type&amp; _v, <span class="keywordtype">bool</span> _swap=<span class="keyword">false</span>)</div><div class="line">      <span class="keyword">static</span> <span class="keywordtype">size_t</span> restore( std::istream&amp; _is, value_type&amp; _v, <span class="keywordtype">bool</span> _swap=<span class="keyword">false</span>)</div></div><!-- fragment --></p>
<p>The flag <code>is_streamable</code> has to be set to <code>true</code>. Else the data cannot be stored at all.</p>
<h5><code>size_of</code> methods </h5>
<p>Since the size of the custom data can be static, which means we know the size at compile time, or the size of it is dynamic, which means me the size is known at runtime, we have to provide the two <code>size_of()</code> methods.</p>
<p>The first declaration is for the static case, while the second for the dynamic case. Though the static case is more simple, it is not straight forward. We cannot simply use <code>sizeof()</code> to determine the data size, because it will return the number ob bytes it needs in memory (possible 32bit alignment). Instead we need the binary size, hence we have to add up the single elements in the struct.</p>
 <div class="fragment"><div class="line">        <span class="keywordflow">return</span> <span class="keyword">sizeof</span>(int)+<span class="keyword">sizeof</span>(<span class="keywordtype">double</span>)+<span class="keyword">sizeof</span>(bool)+<span class="keyword">sizeof</span>(<a class="code" href="a02005.html">OpenMesh::Vec4f</a>); </div></div><!-- fragment --></p>
<p>Actually we would need to sum up the single elements of the vector, but in this case we know for sure the result (4 floats make 16 bytes, which is 32bit aligned therefore <code>sizeof()</code> returns the wanted size). But keep in mind, that this a potential location for errors, when writing custom binary support.</p>
<p>The second declaration is for the dynamic case, where the custom data contains pointers or references. This static member must properly count the data, by disolving the pointers/references, if this data has to be stored as well. In the dynamic stetting the static variant cannot return the size, therefore it must return <code>IO::UnknownSize</code>.</p>
<p>In this case the dynamic variant simply returns the size by calling the static variant, as the sizes are identical for both cases.</p>
<h5><code>store</code> / <code>restore</code> </h5>
<p>For the dynamic case as for the static case, we have to make up a scheme how we would store the data. One option is to store the length of the data and then store the data itself. For instance the type <code>std::string</code> is implemented this way. (We store first the length in a 16bit word (=&gt; max. length 65536), then the characters follow. Hence <code>size_of()</code> returns 2 bytes for the length plus the actual length of the value <code>v</code>.) Since <code><a class="el" href="a03429.html">MyData</a></code> contains only basic types we can implement the necessary methods <code>store</code> and <code>restore</code>, by simply breaking up the data into the basic types using the pre-defined store/restore methods for them:</p>
<p><div class="fragment"><div class="line">      <span class="keyword">static</span> <span class="keywordtype">size_t</span> store(std::ostream&amp; _os, <span class="keyword">const</span> value_type&amp; _v, <span class="keywordtype">bool</span> _swap=<span class="keyword">false</span>)</div><div class="line">      { </div><div class="line">        <span class="keywordtype">size_t</span> bytes;</div><div class="line">        bytes  = IO::store( _os, _v.ival, _swap );</div><div class="line">        bytes += IO::store( _os, _v.dval, _swap );</div><div class="line">        bytes += IO::store( _os, _v.bval, _swap );</div><div class="line">        bytes += IO::store( _os, _v.vec4fval, _swap );</div><div class="line">        <span class="keywordflow">return</span> _os.good() ? bytes : 0;</div><div class="line">      }</div><div class="line">      <span class="keyword">static</span> <span class="keywordtype">size_t</span> restore( std::istream&amp; _is, value_type&amp; _v, <span class="keywordtype">bool</span> _swap=<span class="keyword">false</span>)</div><div class="line">      { </div><div class="line">        <span class="keywordtype">size_t</span> bytes;</div><div class="line">        bytes  = IO::restore( _is, _v.ival, _swap );</div><div class="line">        bytes += IO::restore( _is, _v.dval, _swap );</div><div class="line">        bytes += IO::restore( _is, _v.bval, _swap );</div><div class="line">        bytes += IO::restore( _is, _v.vec4fval, _swap );</div><div class="line">        <span class="keywordflow">return</span> _is.good() ? bytes : 0;</div><div class="line">      }</div></div><!-- fragment --></p>
<p>It's very important, that the store/restore methods count the written/read bytes correctly and return the value. On error both functions must return 0.</p>
<p>A more complex situation is given with the following property</p>
 <div class="fragment"><div class="line"><span class="keyword">typedef</span> std::map&lt; std::string, unsigned int &gt; MyMap;</div><div class="line">  <a class="code" href="a02569.html">OpenMesh::MPropHandleT&lt;MyMap&gt;</a>       mprop_map;</div></div><!-- fragment --></p>
<p>In this case the data contains a container, a map from strings to integer numbers. If we want to store this as well, we need to make up a scheme how the map will be stored in a sequential layout. First we store the number of elements in the map. Then, since the map has an iterator, we simply iterate over all elements and store each pair (key/value). This procedure is equal for the <code>size_of()</code>, <code>store()</code>, and <code>restore()</code> methods. For example the <code>size_of()</code> methods look like this</p>
 <div class="fragment"><div class="line">      <span class="keyword">static</span> <span class="keywordtype">size_t</span> <a class="code" href="a01236.html#a787a7735700a12801c8a505f2c605681">size_of</a>(<span class="keywordtype">void</span>) { <span class="keywordflow">return</span> UnknownSize; }</div><div class="line">      <span class="keyword">static</span> <span class="keywordtype">size_t</span> <a class="code" href="a01236.html#a787a7735700a12801c8a505f2c605681">size_of</a>(<span class="keyword">const</span> value_type&amp; _v) </div><div class="line">      { </div><div class="line">        <span class="keywordflow">if</span> (_v.empty())</div><div class="line">          <span class="keywordflow">return</span> <span class="keyword">sizeof</span>(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>);</div><div class="line">        </div><div class="line">        value_type::const_iterator it = _v.begin();</div><div class="line">        <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>   N     = _v.size();</div><div class="line">        <span class="keywordtype">size_t</span>         bytes = IO::size_of(N);</div><div class="line"></div><div class="line">        <span class="keywordflow">for</span>(;it!=_v.end(); ++it)</div><div class="line">        {</div><div class="line">          bytes += IO::size_of( it-&gt;first );</div><div class="line">          bytes += IO::size_of( it-&gt;second );</div><div class="line">        }</div><div class="line">        <span class="keywordflow">return</span> bytes;</div><div class="line">      }</div></div><!-- fragment --></p>
<p>The implementation of <code>store()</code> and <code>restore()</code> follow a similar pattern.</p>
<p>The given example program does the following steps</p>
<ol type="1">
<li>Create a mesh and generate a cube</li>
<li>Add a few custom properties</li>
<li>Fill them with test data</li>
<li>Make the properties persistent</li>
<li>Store mesh in a file named 'persistent-check.om'</li>
<li>Clear the mesh</li>
<li>Restore mesh</li>
<li>Check the content on equality with the test data.</li>
</ol>
<p>Since the example is a little bit longer than usual the source is in several files. The main program is in <code>persistence.cc</code>, the cube generator in <code>generate_cube.hh</code>, <code>stats.hh</code> provides little tools to display information about the mesh and the properties, the file <code>fill_props.hh</code> providing the test data, and <code>int2roman.hh/</code>.cc, which is used in fill_props.hh. All necessary parts are in <code>persistence.cc</code>, which is displayed in full length below. For the other files please have a look in the directory <code>OpenMesh/Doc/Tutorial/10-persistence/</code>.</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &lt;iostream&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;string&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;map&gt;</span></div><div class="line"><span class="comment">// -------------------- OpenMesh</span></div><div class="line"><span class="preprocessor">#include &lt;OpenMesh/Core/IO/MeshIO.hh&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh&gt;</span></div><div class="line"><span class="comment">// -------------------- little helper</span></div><div class="line"><span class="preprocessor">#include &quot;generate_cube.hh&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;stats.hh&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;fill_props.hh&quot;</span></div><div class="line"></div><div class="line"><span class="comment">// ----------------------------------------------------------------------------</span></div><div class="line"></div><div class="line"><span class="comment">// Set to 1 to use an PolyMesh type.</span></div><div class="line"><span class="preprocessor">#define UsePolyMesh 1</span></div><div class="line"></div><div class="line"><span class="comment">// ----------------------------------------------------------------------------</span></div><div class="line"></div><div class="line"><span class="keyword">using namespace </span><a class="code" href="a01233.html">OpenMesh</a>;</div><div class="line"></div><div class="line"><span class="comment">// ----------------------------------------------------------------------------</span></div><div class="line"></div><div class="line"><span class="keyword">typedef</span> <a class="code" href="a02377.html">TriMesh_ArrayKernelT&lt;&gt;</a>  <a class="code" href="a02377.html">TriMesh</a>;</div><div class="line"><span class="keyword">typedef</span> <a class="code" href="a02385.html">PolyMesh_ArrayKernelT&lt;&gt;</a> <a class="code" href="a02385.html">PolyMesh</a>;</div><div class="line"></div><div class="line"><span class="preprocessor">#if UsePolyMesh</span></div><div class="line"><span class="keyword">typedef</span> PolyMesh Mesh;</div><div class="line"><span class="preprocessor">#else</span></div><div class="line"><span class="keyword">typedef</span> TriMesh Mesh;</div><div class="line"><span class="preprocessor">#endif</span></div><div class="line"></div><div class="line"><span class="comment">// ----------------------------------------------------------------------------</span></div><div class="line"></div><div class="line"><span class="preprocessor">#ifndef DOXY_IGNORE_THIS</span></div><div class="line"></div><div class="line"><span class="keyword">struct </span><a class="code" href="a03429.html">MyData</a></div><div class="line">{</div><div class="line">  <span class="keywordtype">int</span>             ival;</div><div class="line">  <span class="keywordtype">double</span>          dval;</div><div class="line">  <span class="keywordtype">bool</span>            bval;</div><div class="line">  <a class="code" href="a02005.html">OpenMesh::Vec4f</a> vec4fval;</div><div class="line"></div><div class="line">  <a class="code" href="a03429.html">MyData</a>()</div><div class="line">    : ival(0), dval(0.0), bval(false)</div><div class="line">  { }</div><div class="line"></div><div class="line">  <a class="code" href="a03429.html">MyData</a>( <span class="keyword">const</span> <a class="code" href="a03429.html">MyData</a>&amp; _cpy )</div><div class="line">    : ival(_cpy.ival), dval(_cpy.dval), bval(_cpy.bval), </div><div class="line">      vec4fval(_cpy.vec4fval)</div><div class="line">  { }</div><div class="line"></div><div class="line"></div><div class="line">  <span class="comment">// ---------- assignment</span></div><div class="line"></div><div class="line">  <a class="code" href="a03429.html">MyData</a>&amp; operator = (<span class="keyword">const</span> <a class="code" href="a03429.html">MyData</a>&amp; _rhs) </div><div class="line">  { </div><div class="line">    ival = _rhs.ival; </div><div class="line">    dval = _rhs.dval;</div><div class="line">    bval = _rhs.bval;</div><div class="line">    vec4fval = _rhs.vec4fval;</div><div class="line">    <span class="keywordflow">return</span> *<span class="keyword">this</span>;</div><div class="line">  }</div><div class="line"></div><div class="line">  <a class="code" href="a03429.html">MyData</a>&amp; operator = (<span class="keywordtype">int</span>    _rhs) { ival = _rhs; <span class="keywordflow">return</span> *<span class="keyword">this</span>; }</div><div class="line">  <a class="code" href="a03429.html">MyData</a>&amp; operator = (<span class="keywordtype">double</span> _rhs) { dval = _rhs; <span class="keywordflow">return</span> *<span class="keyword">this</span>; }</div><div class="line">  <a class="code" href="a03429.html">MyData</a>&amp; operator = (<span class="keywordtype">bool</span>   _rhs) { bval = _rhs; <span class="keywordflow">return</span> *<span class="keyword">this</span>; }</div><div class="line">  <a class="code" href="a03429.html">MyData</a>&amp; operator = (<span class="keyword">const</span> <a class="code" href="a02005.html">OpenMesh::Vec4f</a>&amp; _rhs) </div><div class="line">  { vec4fval = _rhs; <span class="keywordflow">return</span> *<span class="keyword">this</span>; }</div><div class="line"></div><div class="line"></div><div class="line">  <span class="comment">// ---------- comparison</span></div><div class="line"></div><div class="line">  <span class="keywordtype">bool</span> operator == (<span class="keyword">const</span> <a class="code" href="a03429.html">MyData</a>&amp; _rhs)<span class="keyword"> const</span></div><div class="line"><span class="keyword">  </span>{ </div><div class="line">    <span class="keywordflow">return</span> ival == _rhs.ival</div><div class="line">      &amp;&amp;   dval == _rhs.dval</div><div class="line">      &amp;&amp;   bval == _rhs.bval</div><div class="line">      &amp;&amp;   vec4fval == _rhs.vec4fval;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordtype">bool</span> operator != (<span class="keyword">const</span> <a class="code" href="a03429.html">MyData</a>&amp; _rhs)<span class="keyword"> const </span>{ <span class="keywordflow">return</span> !(*<span class="keyword">this</span> == _rhs); }</div><div class="line"></div><div class="line">};</div><div class="line"></div><div class="line"><span class="preprocessor">#endif</span></div><div class="line"></div><div class="line"></div><div class="line"><span class="comment">// ----------------------------------------------------------------------------</span></div><div class="line"></div><div class="line"><span class="keyword">typedef</span> std::map&lt; std::string, unsigned int &gt; MyMap;</div><div class="line"></div><div class="line"></div><div class="line"><span class="comment">// ----------------------------------------------------------------------------</span></div><div class="line"></div><div class="line"><span class="preprocessor">#ifndef DOXY_IGNORE_THIS</span></div><div class="line"></div><div class="line"><span class="keyword">namespace </span><a class="code" href="a01233.html">OpenMesh</a> {</div><div class="line">  <span class="keyword">namespace </span>IO {</div><div class="line"></div><div class="line">    <span class="comment">// support persistence for struct MyData</span></div><div class="line"></div><div class="line">    <span class="keyword">template</span> &lt;&gt; <span class="keyword">struct </span>binary&lt;<a class="code" href="a03429.html">MyData</a>&gt;</div><div class="line">    {</div><div class="line">      <span class="keyword">typedef</span> <a class="code" href="a03429.html">MyData</a> value_type;</div><div class="line"></div><div class="line">      <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">bool</span> is_streamable = <span class="keyword">true</span>;</div><div class="line"></div><div class="line">      <span class="comment">// return binary size of the value</span></div><div class="line"></div><div class="line">      <span class="keyword">static</span> <span class="keywordtype">size_t</span> <a class="code" href="a01236.html#a787a7735700a12801c8a505f2c605681">size_of</a>(<span class="keywordtype">void</span>) </div><div class="line">      { </div><div class="line">        <span class="keywordflow">return</span> <span class="keyword">sizeof</span>(int)+<span class="keyword">sizeof</span>(<span class="keywordtype">double</span>)+<span class="keyword">sizeof</span>(bool)+<span class="keyword">sizeof</span>(<a class="code" href="a02005.html">OpenMesh::Vec4f</a>); </div><div class="line">      }</div><div class="line"></div><div class="line">      <span class="keyword">static</span> <span class="keywordtype">size_t</span> <a class="code" href="a01236.html#a787a7735700a12801c8a505f2c605681">size_of</a>(<span class="keyword">const</span> value_type&amp;) </div><div class="line">      { </div><div class="line">        <span class="keywordflow">return</span> <a class="code" href="a01236.html#a787a7735700a12801c8a505f2c605681">size_of</a>(); </div><div class="line">      }</div><div class="line"></div><div class="line">      <span class="keyword">static</span> <span class="keywordtype">size_t</span> store(std::ostream&amp; _os, <span class="keyword">const</span> value_type&amp; _v, <span class="keywordtype">bool</span> _swap=<span class="keyword">false</span>)</div><div class="line">      { </div><div class="line">        <span class="keywordtype">size_t</span> bytes;</div><div class="line">        bytes  = IO::store( _os, _v.ival, _swap );</div><div class="line">        bytes += IO::store( _os, _v.dval, _swap );</div><div class="line">        bytes += IO::store( _os, _v.bval, _swap );</div><div class="line">        bytes += IO::store( _os, _v.vec4fval, _swap );</div><div class="line">        <span class="keywordflow">return</span> _os.good() ? bytes : 0;</div><div class="line">      }</div><div class="line"></div><div class="line">      <span class="keyword">static</span> <span class="keywordtype">size_t</span> restore( std::istream&amp; _is, value_type&amp; _v, <span class="keywordtype">bool</span> _swap=<span class="keyword">false</span>)</div><div class="line">      { </div><div class="line">        <span class="keywordtype">size_t</span> bytes;</div><div class="line">        bytes  = IO::restore( _is, _v.ival, _swap );</div><div class="line">        bytes += IO::restore( _is, _v.dval, _swap );</div><div class="line">        bytes += IO::restore( _is, _v.bval, _swap );</div><div class="line">        bytes += IO::restore( _is, _v.vec4fval, _swap );</div><div class="line">        <span class="keywordflow">return</span> _is.good() ? bytes : 0;</div><div class="line">      }</div><div class="line">    };</div><div class="line"></div><div class="line"></div><div class="line">    <span class="keyword">template</span> &lt;&gt; <span class="keyword">struct </span>binary&lt; MyMap &gt;</div><div class="line">    {</div><div class="line">      <span class="keyword">typedef</span> MyMap value_type;</div><div class="line"></div><div class="line">      <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">bool</span> is_streamable = <span class="keyword">true</span>;</div><div class="line"></div><div class="line">      <span class="comment">// return generic binary size of self, if known</span></div><div class="line">      <span class="keyword">static</span> <span class="keywordtype">size_t</span> <a class="code" href="a01236.html#a787a7735700a12801c8a505f2c605681">size_of</a>(<span class="keywordtype">void</span>) { <span class="keywordflow">return</span> UnknownSize; }</div><div class="line"></div><div class="line">      <span class="comment">// return binary size of the value</span></div><div class="line">      <span class="keyword">static</span> <span class="keywordtype">size_t</span> <a class="code" href="a01236.html#a787a7735700a12801c8a505f2c605681">size_of</a>(<span class="keyword">const</span> value_type&amp; _v) </div><div class="line">      { </div><div class="line">        <span class="keywordflow">if</span> (_v.empty())</div><div class="line">          <span class="keywordflow">return</span> <span class="keyword">sizeof</span>(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>);</div><div class="line">        </div><div class="line">        value_type::const_iterator it = _v.begin();</div><div class="line">        <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>   N     = _v.size();</div><div class="line">        <span class="keywordtype">size_t</span>         bytes = <a class="code" href="a01236.html#a787a7735700a12801c8a505f2c605681">IO::size_of</a>(N);</div><div class="line"></div><div class="line">        <span class="keywordflow">for</span>(;it!=_v.end(); ++it)</div><div class="line">        {</div><div class="line">          bytes += <a class="code" href="a01236.html#a787a7735700a12801c8a505f2c605681">IO::size_of</a>( it-&gt;first );</div><div class="line">          bytes += <a class="code" href="a01236.html#a787a7735700a12801c8a505f2c605681">IO::size_of</a>( it-&gt;second );</div><div class="line">        }</div><div class="line">        <span class="keywordflow">return</span> bytes;</div><div class="line">      }</div><div class="line"></div><div class="line">      <span class="keyword">static</span> </div><div class="line">      <span class="keywordtype">size_t</span> store(std::ostream&amp; _os, <span class="keyword">const</span> value_type&amp; _v, <span class="keywordtype">bool</span> _swap=<span class="keyword">false</span>)</div><div class="line">      { </div><div class="line">        <span class="keywordtype">size_t</span>   bytes = 0;</div><div class="line">        <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> N = _v.size();</div><div class="line"></div><div class="line">        value_type::const_iterator it = _v.begin();</div><div class="line"></div><div class="line">        bytes += IO::store( _os, N, _swap );</div><div class="line"></div><div class="line">        <span class="keywordflow">for</span> (; it != _v.end() &amp;&amp; _os.good(); ++it)</div><div class="line">        {</div><div class="line">          bytes += IO::store( _os, it-&gt;first, _swap );</div><div class="line">          bytes += IO::store( _os, it-&gt;second, _swap );</div><div class="line">        }</div><div class="line">        <span class="keywordflow">return</span> _os.good() ? bytes : 0;</div><div class="line">      }</div><div class="line"></div><div class="line">      <span class="keyword">static</span> </div><div class="line">      <span class="keywordtype">size_t</span> restore( std::istream&amp; _is, value_type&amp; _v, <span class="keywordtype">bool</span> _swap=<span class="keyword">false</span>)</div><div class="line">      { </div><div class="line">        <span class="keywordtype">size_t</span>   bytes = 0;</div><div class="line">        <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> N = 0;</div><div class="line"></div><div class="line">        _v.clear();</div><div class="line"></div><div class="line">        bytes += IO::restore( _is, N, _swap );</div><div class="line">        value_type::key_type key;</div><div class="line">        value_type::mapped_type  val;</div><div class="line"></div><div class="line">        <span class="keywordflow">for</span> (<span class="keywordtype">size_t</span> i=0; i&lt;N &amp;&amp; _is.good(); ++i)</div><div class="line">        {          </div><div class="line">          bytes += IO::restore( _is, key, _swap );</div><div class="line">          bytes += IO::restore( _is, val, _swap );</div><div class="line">          _v[key] = val;</div><div class="line">        }</div><div class="line">        <span class="keywordflow">return</span> _is.good() ? bytes : 0;</div><div class="line">      }</div><div class="line">    };</div><div class="line"></div><div class="line">  }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="preprocessor">#endif</span></div><div class="line"></div><div class="line"></div><div class="line"><span class="comment">// ----------------------------------------------------------------------------</span></div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">  <span class="comment">//</span></div><div class="line">  Mesh mesh;</div><div class="line"></div><div class="line">  </div><div class="line">  <span class="comment">// generate a geometry</span></div><div class="line">  generate_cube&lt;Mesh&gt;(mesh);</div><div class="line"></div><div class="line"></div><div class="line">  <span class="comment">// should display 8 vertices, 18/12 edges, 12/6 faces (Tri/Poly)</span></div><div class="line">  mesh_stats(mesh);</div><div class="line"></div><div class="line"></div><div class="line">  <span class="comment">// print out information about properties</span></div><div class="line">  mesh_property_stats(mesh);</div><div class="line"></div><div class="line"></div><div class="line">  std::cout &lt;&lt; <span class="stringliteral">&quot;Define some custom properties..\n&quot;</span>;</div><div class="line"></div><div class="line">  <a class="code" href="a02553.html">OpenMesh::VPropHandleT&lt;float&gt;</a>       vprop_float;</div><div class="line">  <a class="code" href="a02561.html">OpenMesh::EPropHandleT&lt;bool&gt;</a>        eprop_bool;</div><div class="line">  <a class="code" href="a02565.html">OpenMesh::FPropHandleT&lt;std::string&gt;</a> fprop_string;</div><div class="line">  <a class="code" href="a02557.html">OpenMesh::HPropHandleT&lt;MyData&gt;</a>      hprop_mydata;</div><div class="line">  <a class="code" href="a02569.html">OpenMesh::MPropHandleT&lt;MyMap&gt;</a>       mprop_map;</div><div class="line">    </div><div class="line">  std::cout &lt;&lt; <span class="stringliteral">&quot;.. and registrate them at the mesh object.\n&quot;</span>;</div><div class="line"></div><div class="line">  mesh.add_property(vprop_float,  <span class="stringliteral">&quot;vprop_float&quot;</span>);</div><div class="line">  mesh.add_property(eprop_bool,   <span class="stringliteral">&quot;eprop_bool&quot;</span>);</div><div class="line">  mesh.add_property(fprop_string, <span class="stringliteral">&quot;fprop_string&quot;</span>);</div><div class="line">  mesh.add_property(hprop_mydata, <span class="stringliteral">&quot;hprop_mydata&quot;</span>);</div><div class="line">  mesh.add_property(mprop_map,    <span class="stringliteral">&quot;mprop_map&quot;</span>);</div><div class="line"></div><div class="line"></div><div class="line">  mesh_property_stats(mesh);</div><div class="line"></div><div class="line"></div><div class="line">  std::cout &lt;&lt; <span class="stringliteral">&quot;Now let&#39;s fill the props..\n&quot;</span>;</div><div class="line"></div><div class="line">  fill_props(mesh, vprop_float);</div><div class="line">  fill_props(mesh, eprop_bool);</div><div class="line">  fill_props(mesh, fprop_string);</div><div class="line">  fill_props(mesh, hprop_mydata);</div><div class="line">  fill_props(mesh, mprop_map);</div><div class="line"></div><div class="line"></div><div class="line">  std::cout &lt;&lt; <span class="stringliteral">&quot;Check props..\n&quot;</span>;</div><div class="line"><span class="preprocessor">#define CHK_PROP( PH ) \</span></div><div class="line"><span class="preprocessor">  std::cout &lt;&lt; &quot;  &quot; &lt;&lt; #PH &lt;&lt; &quot; &quot; \</span></div><div class="line"><span class="preprocessor">            &lt;&lt; (fill_props(mesh, PH, true)?&quot;ok\n&quot;:&quot;error\n&quot;)</span></div><div class="line"></div><div class="line">  CHK_PROP(vprop_float);</div><div class="line">  CHK_PROP(eprop_bool);</div><div class="line">  CHK_PROP(fprop_string);</div><div class="line">  CHK_PROP(hprop_mydata);</div><div class="line">  CHK_PROP(mprop_map);</div><div class="line"><span class="preprocessor">#undef CHK_PROP</span></div><div class="line"></div><div class="line"></div><div class="line">  std::cout &lt;&lt; <span class="stringliteral">&quot;Set persistent flag..\n&quot;</span>;</div><div class="line"><span class="preprocessor">#define SET_PERS( PH ) \</span></div><div class="line"><span class="preprocessor">    mesh.property(PH).set_persistent(true); \</span></div><div class="line"><span class="preprocessor">    std::cout &lt;&lt; &quot;  &quot; &lt;&lt; #PH &lt;&lt; &quot; &quot; \</span></div><div class="line"><span class="preprocessor">              &lt;&lt; (mesh.property(PH).persistent()?&quot;ok\n&quot;:&quot;failed!\n&quot;)</span></div><div class="line"></div><div class="line">  mesh.property(vprop_float).set_persistent(<span class="keyword">true</span>);</div><div class="line">  std::cout &lt;&lt; <span class="stringliteral">&quot;  vprop_float &quot;</span></div><div class="line">            &lt;&lt; (mesh.property(vprop_float).persistent()?<span class="stringliteral">&quot;ok\n&quot;</span>:<span class="stringliteral">&quot;failed!\n&quot;</span>);</div><div class="line">  </div><div class="line">  SET_PERS( eprop_bool );</div><div class="line">  SET_PERS( fprop_string );</div><div class="line">  SET_PERS( hprop_mydata );</div><div class="line">  mesh.mproperty(mprop_map).set_persistent(<span class="keyword">true</span>);</div><div class="line">  std::cout &lt;&lt; <span class="stringliteral">&quot;  mprop_map &quot;</span></div><div class="line">            &lt;&lt; (mesh.mproperty(mprop_map).persistent()?<span class="stringliteral">&quot;ok\n&quot;</span>:<span class="stringliteral">&quot;failed!\n&quot;</span>);</div><div class="line"> </div><div class="line"></div><div class="line">  std::cout &lt;&lt; <span class="stringliteral">&quot;Write mesh..&quot;</span>;</div><div class="line">  <span class="keywordflow">if</span> (<a class="code" href="a01236.html#a18286a792ebf896872f5e26182fc5c7b">IO::write_mesh</a>( mesh, <span class="stringliteral">&quot;persistence-check.om&quot;</span> ))</div><div class="line">    std::cout &lt;&lt; <span class="stringliteral">&quot;  ok\n&quot;</span>;</div><div class="line">  <span class="keywordflow">else</span></div><div class="line">  {</div><div class="line">    std::cout &lt;&lt; <span class="stringliteral">&quot;  failed\n&quot;</span>;</div><div class="line">    <span class="keywordflow">return</span> 1;</div><div class="line">  }</div><div class="line"></div><div class="line"></div><div class="line">  std::cout &lt;&lt; <span class="stringliteral">&quot;Clear mesh\n&quot;</span>;</div><div class="line">  mesh.clear();</div><div class="line">  mesh_stats(mesh, <span class="stringliteral">&quot;  &quot;</span>);</div><div class="line">  </div><div class="line"></div><div class="line">  std::cout &lt;&lt; <span class="stringliteral">&quot;Read back mesh..&quot;</span>;</div><div class="line">  <span class="keywordflow">try</span></div><div class="line">  {</div><div class="line">    <span class="keywordflow">if</span> (<a class="code" href="a01236.html#ac417960ec28ffdd7e7003a2b1ebb2d1c">IO::read_mesh</a>( mesh, <span class="stringliteral">&quot;persistence-check.om&quot;</span> ))</div><div class="line">      std::cout &lt;&lt; <span class="stringliteral">&quot;  ok\n&quot;</span>;</div><div class="line">    <span class="keywordflow">else</span></div><div class="line">    {</div><div class="line">      std::cout &lt;&lt; <span class="stringliteral">&quot;  failed!\n&quot;</span>;</div><div class="line">      <span class="keywordflow">return</span> 1;</div><div class="line">    }</div><div class="line">    mesh_stats(mesh, <span class="stringliteral">&quot;  &quot;</span>);</div><div class="line">  }</div><div class="line">  <span class="keywordflow">catch</span>( std::exception &amp;x )</div><div class="line">  {</div><div class="line">    std::cerr &lt;&lt; x.what() &lt;&lt; std::endl;</div><div class="line">    <span class="keywordflow">return</span> 1;</div><div class="line">  }</div><div class="line"></div><div class="line"></div><div class="line">  std::cout &lt;&lt; <span class="stringliteral">&quot;Check props..\n&quot;</span>;</div><div class="line"><span class="preprocessor">#define CHK_PROP( PH ) \</span></div><div class="line"><span class="preprocessor">  std::cout &lt;&lt; &quot;  &quot; &lt;&lt; #PH &lt;&lt; &quot; &quot; \</span></div><div class="line"><span class="preprocessor">            &lt;&lt; (fill_props(mesh, PH, true)?&quot;ok\n&quot;:&quot;error\n&quot;)</span></div><div class="line">  CHK_PROP(vprop_float);</div><div class="line">  CHK_PROP(eprop_bool);</div><div class="line">  CHK_PROP(fprop_string);</div><div class="line">  CHK_PROP(hprop_mydata);</div><div class="line">  CHK_PROP(mprop_map);</div><div class="line"><span class="preprocessor">#undef CHK_PROP</span></div><div class="line"></div><div class="line">  <span class="keywordflow">return</span> 0;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">// end of file</span></div><div class="line"><span class="comment">// ============================================================================</span></div></div><!-- fragment --> </div></div><!-- contents -->
</div><!-- doc-content -->
<hr>
<address>
<small>
<a href="http://www.rwth-graphics.de" style="text-decoration:none;">
</a>
Project <b>OpenMesh</b>, 
&copy;&nbsp; Computer Graphics Group, RWTH Aachen.
Documentation generated using 
<a class="el" href="http://www.doxygen.org/index.html">
<b>doxygen</b>
</a>.
</small>
</address>
</body>
</html>
